from django.contrib.auth.models import Group, Permission, User
from django.db import transaction
from rest_framework import serializers


class PermissionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Permission
        fields = (
            "id",
            "name",
            "content_type",
            "codename",
        )
        read_only_fields = ("id",)


class RoleSerializer(serializers.ModelSerializer):

    permissions_info = PermissionSerializer(
        read_only=True,
        many=True,
        source="permissions",
    )

    limit = serializers.SerializerMethodField()

    def get_limit(self, obj):
        all_perms = list(obj.permissions.all().values_list("codename", flat=True))
        
        return ",".join(all_perms)

    user_ids = serializers.SerializerMethodField()

    def get_user_ids(self, obj):
        return list(obj.user_set.all().values_list("id", flat=True))

    class Meta:
        model = Group
        fields = "__all__"
        read_only_fields = ("id",)


class EditRoleSerializer(serializers.ModelSerializer):
    limit = serializers.CharField(allow_null=True, read_only=True)

    perms = serializers.ListField(
        child=serializers.CharField(),
        write_only=True,
        allow_null=True,
    )

    def create(self, validated_data):
        perms = validated_data.pop("limit", "").split(",")

        with transaction.atomic():
            group = super(EditRoleSerializer, self).create(validated_data)
            permissions = list(Permission.objects.filter(codename__in=perms))
            group.permissions.set(permissions)
        return group

    def update(self, instance, validated_data):

        perms = validated_data.pop("limit", "").split(",")
        with transaction.atomic():
            group = super(EditRoleSerializer, self).update(instance, validated_data)

            permissions = list(Permission.objects.filter(codename__in=perms))
            group.permissions.set(permissions)
        return group

    class Meta:
        model = Group
        fields = (
            "id",
            "name",
            "perms",
            "limit",
        )


class EmbedGroupSerializer(serializers.ModelSerializer):

    limit = serializers.SerializerMethodField()

    def get_limit(self, obj):
        all_perms = list(obj.permissions.all().values_list("codename", flat=True))
        sso_perms = [
            perm.split(".")[1] for perm in all_perms if perm.split(".")[0] == "main"
        ]
        return ",".join(sso_perms)

    class Meta:
        model = Group
        fields = (
            "id",
            "name",
            "limit",
        )


class UserSerializer(serializers.ModelSerializer):

    groups = EmbedGroupSerializer(many=True, read_only=True)
    group_ids = serializers.PrimaryKeyRelatedField(
        help_text="角色修改,传id值",
        many=True,
        queryset=Group.objects.filter(),
        write_only=True,
        default=None,
    )

    def update(self, instance, validated_data):
        group_ids = validated_data.pop("group_ids", None)
        instance = super(UserSerializer, self).update(instance, validated_data)
        if isinstance(group_ids, list):
            instance.groups.set(group_ids)
        return instance

    class Meta:
        model = User
        exclude = ["password"]
        extra_kwargs = {
            "id": {"read_only": True},
            "username": {"read_only": True},
            "date_joined": {"read_only": True},
        }


class EditUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(allow_null=True, read_only=True)

    def create(self, validated_data):
        instance = super(EditUserSerializer, self).create(validated_data)
        if validated_data.get("password"):
            instance.set_password(validated_data.get("password"))
        return instance

    def update(self, instance, validated_data):
        instance = super(EditUserSerializer, self).update(instance, validated_data)
        if validated_data.get("password"):
            instance.set_password(validated_data.get("password"))
        return instance

    class Meta:
        model = User
        fields = "__all__"


class AssignUserRoleSerializer(serializers.Serializer):

    user_list = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.filter(),
        many=True,
    )
    role_list = serializers.PrimaryKeyRelatedField(
        queryset=Group.objects.filter(),
        many=True,
    )

    def validate(self, attrs):
        user_list = attrs["user_list"]
        group_list = attrs["role_list"]

        for user in user_list:
            user.groups.set(group_list)

        return {
            "user_list": map(lambda x: x.id, user_list),
            "group_list": map(lambda x: x.id, user_list),
        }
